# coding=utf-8
# 2019/12/17: 首个记录
# 2020/4/1: 导入bi_common
# 2020/5/26: 支持协议v2
# 2020/7/28: 完善枚举类型定义
# 2020/8/3: 增加枚举类型==/!=重载
# 2020/8/5: 枚举值类改为继承EnumValue
# 2020/11/6: 增加停车位是否被占用字段

import bi_common as bi


# 交通元素类别
class TrafficElementTypeValue(bi.EnumValue):
    def __str__(self):
        if self.val == 1:
            return 'SPEED_LIMIT'
        elif self.val == 2:
            return 'STOP_SIGN'
        elif self.val == 3:
            return 'TRAFFIC_LIGHT'
        elif self.val == 4:
            return 'STOP_LINE'
        elif self.val == 5:
            return 'SPEED_BUMP'
        elif self.val == 6:
            return 'ARROW_MARK'
        elif self.val == 7:
            return 'PROHIBITION_ZONE'
        elif self.val == 8:
            return 'PARKING_SLOT'
        elif self.val == 9:
            return 'ZEBRA_CROSSING'
        else:
            return 'INVALID'


class TrafficElementType:
    INVALID = TrafficElementTypeValue(0)  # 无效
    SPEED_LIMIT = TrafficElementTypeValue(1)  # 限速标志
    STOP_SIGN = TrafficElementTypeValue(2)  # 停止标志
    TRAFFIC_LIGHT = TrafficElementTypeValue(3)  # 交通信号灯
    STOP_LINE = TrafficElementTypeValue(4)  # 停止线
    SPEED_BUMP = TrafficElementTypeValue(5)  # 减速带
    ARROW_MARK = TrafficElementTypeValue(6)  # 路面箭头
    PROHIBITION_ZONE = TrafficElementTypeValue(7)  # 禁停区
    PARKING_SLOT = TrafficElementTypeValue(8)  # 停车位
    ZEBRA_CROSSING = TrafficElementTypeValue(9)  # 斑马线

    def __init__(self):
        pass


# 交通灯状态
class TrafficLightStateValue(bi.EnumValue):
    def __str__(self):
        if self.val == 1:
            return 'STOP'
        elif self.val == 2:
            return 'CONTINUE'
        elif self.val == 3:
            return 'CAUTION'
        elif self.val == 4:
            return 'ALLOW'
        elif self.val == 5:
            return 'ALLOW_FLASH'
        elif self.val == 6:
            return 'STOP_FLASH'
        else:
            return 'INVALID'


class TrafficLightState:
    INVALID = TrafficLightStateValue(0)  # 无效
    STOP = TrafficLightStateValue(1)  # 红灯
    CONTINUE = TrafficLightStateValue(2)  # 黄灯
    CAUTION = TrafficLightStateValue(3)  # 黄灯闪烁
    ALLOW = TrafficLightStateValue(4)  # 绿灯
    ALLOW_FLASH = TrafficLightStateValue(5)  # 绿灯闪烁
    STOP_FLASH = TrafficLightStateValue(6)  # 红灯闪烁

    def __init__(self):
        pass


# 停车位状态
class ParkingSlotOccupancyValue(bi.EnumValue):
    def __str__(self):
        if self.val == 1:
            return 'NOT_OCCUPIED'
        elif self.val == 2:
            return 'OCCUPIED'
        else:
            return 'UNKNOWN'


class ParkingSlotOccupancy:
    UNKNOWN = ParkingSlotOccupancyValue(0)  # 未知
    NOT_OCCUPIED = ParkingSlotOccupancyValue(1)  # 未被占用
    OCCUPIED = ParkingSlotOccupancyValue(2)  # 被占用

    def __init__(self):
        pass


# 箭头组合
class ArrowCombination:
    def __init__(self):
        self.valid = False  # 有效标志位
        self.go_straight = False  # 直行
        self.turn_left = False  # 左转
        self.turn_right = False  # 右转
        self.u_turn = False  # 调头


# 交通元素基类
class TrafficElement:
    def __init__(self):
        self.id = 0  # 交通元素ID，0表示无效
        self.raw_id_valid = False
        self.raw_id = 0  # 交通元素的原始ID


# 限速标志
class SpeedLimit(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.limit_speed = 0  # 限速 KPH
        self.pos_x_valid = False
        self.pos_x = 0.0  # 纵向位置 m
        self.pos_y_valid = False
        self.pos_y = 0.0  # 横向位置 m
        self.pos_z_valid = False
        self.pos_z = 0.0  # 垂直位置 m


# 停止标志
class StopSign(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.pos_x_valid = False
        self.pos_x = 0.0  # 纵向位置 m
        self.pos_y_valid = False
        self.pos_y = 0.0  # 横向位置 m
        self.pos_z_valid = False
        self.pos_z = 0.0  # 垂直位置 m


# 交通信号灯
class TrafficLight(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.state = TrafficLightState.INVALID  # 信号灯状态
        self.arrows = ArrowCombination()  # 信号灯的箭头组合，若不分方向(实心圆信号)则valid为False
        self.pos_x_valid = False
        self.pos_x = 0.0  # 纵向位置 m
        self.pos_y_valid = False
        self.pos_y = 0.0  # 横向位置 m
        self.pos_z_valid = False
        self.pos_z = 0.0  # 垂直位置 m


# 停止线
class StopLine(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.distance = 0.0  # 停止线与x轴相交位置 m
        self.heading_valid = False
        self.heading = 0.0  # 停止线法线朝向，单位°，逆时针为正方向


# 减速带
class SpeedBump(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.distance = 0.0  # 减速带与x轴相交位置 m
        self.heading_valid = False
        self.heading = 0.0  # 减速带法线朝向，单位°，逆时针为正方向


# 路面箭头
class ArrowMark(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.arrows = ArrowCombination()  # 路面标志的箭头组合
        self.pos_x_valid = False
        self.pos_x = 0.0  # 纵向位置 m
        self.pos_y_valid = False
        self.pos_y = 0.0  # 横向位置 m


# 禁停区
class ProhibitionZone(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.center_x = 0.0  # 禁停区中央的纵向位置 m
        self.center_y = 0.0  # 禁停区中央的横向位置 m
        self.width = 0.0  # 禁停区的宽度 m
        self.length = 0.0  # 禁停区的长度 m
        self.heading_valid = False
        self.heading = 0.0  # 禁停区的朝向(沿长度方向)，单位°，逆时针为正方向


# 停车位
class ParkingSlot(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.center_x = 0.0  # 停车位中央的纵向位置 m
        self.center_y = 0.0  # 停车位中央的横向位置 m
        self.width = 0.0  # 停车位的宽度 m
        self.length = 0.0  # 停车位的长度 m
        self.heading_valid = False
        self.heading = 0.0  # 停车位的朝向(沿长度方向)，单位°，逆时针为正方向
        self.occupancy = ParkingSlotOccupancy.UNKNOWN  # 停车位是否被占用


# 斑马线
class ZebraCrossing(TrafficElement):
    def __init__(self):
        TrafficElement.__init__(self)
        self.near_distance = 0.0  # 斑马线近端与x轴相交位置 m
        self.far_distance_valid = False
        self.far_distance = 0.0  # 斑马线远端与x轴相交位置 m
        self.heading_valid = False
        self.heading = 0.0  # 斑马线的朝向，单位°，逆时针为正方向


# 交通信息样本
class TrafficSample:
    def __init__(self):
        self.time = 0.0  # 时间戳 s
        self.elements = []  # 交通元素列表

    # 转通用样本，用于样本输出
    def to_general_sample(self, channel):
        output = bi.agency.create_general_sample()
        output.protocol = "traffic-sample-v2@" + str(channel)
        output.time = self.time
        types = []
        offsets = []
        sizes = []
        datas = []
        total_data_size = 0
        for elem in self.elements:
            elem_data = []
            if isinstance(elem, SpeedLimit):
                types.append(TrafficElementType.SPEED_LIMIT)
                elem_data.append(elem.limit_speed)
                elem_data.append(elem.pos_x if elem.pos_x_valid else None)
                elem_data.append(elem.pos_y if elem.pos_y_valid else None)
                elem_data.append(elem.pos_z if elem.pos_z_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, StopSign):
                types.append(TrafficElementType.STOP_SIGN)
                elem_data.append(elem.pos_x if elem.pos_x_valid else None)
                elem_data.append(elem.pos_y if elem.pos_y_valid else None)
                elem_data.append(elem.pos_z if elem.pos_z_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, TrafficLight):
                types.append(TrafficElementType.TRAFFIC_LIGHT)
                elem_data.append(elem.state.val)
                elem_data.append(elem.pos_x if elem.pos_x_valid else None)
                elem_data.append(elem.pos_y if elem.pos_y_valid else None)
                elem_data.append(elem.pos_z if elem.pos_z_valid else None)
                if elem.arrows.valid:
                    elem_data.append(elem.arrows.go_straight)
                    elem_data.append(elem.arrows.turn_left)
                    elem_data.append(elem.arrows.turn_right)
                    elem_data.append(elem.arrows.u_turn)
                else:
                    elem_data.append(None)
                    elem_data.append(None)
                    elem_data.append(None)
                    elem_data.append(None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, StopLine):
                types.append(TrafficElementType.STOP_LINE)
                elem_data.append(elem.distance)
                elem_data.append(elem.heading if elem.heading_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, SpeedBump):
                types.append(TrafficElementType.SPEED_BUMP)
                elem_data.append(elem.distance)
                elem_data.append(elem.heading if elem.heading_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, ArrowMark):
                types.append(TrafficElementType.ARROW_MARK)
                elem_data.append(elem.arrows.go_straight)
                elem_data.append(elem.arrows.turn_left)
                elem_data.append(elem.arrows.turn_right)
                elem_data.append(elem.arrows.u_turn)
                elem_data.append(elem.pos_x if elem.pos_x_valid else None)
                elem_data.append(elem.pos_y if elem.pos_y_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, ProhibitionZone):
                types.append(TrafficElementType.PROHIBITION_ZONE)
                elem_data.append(elem.center_x)
                elem_data.append(elem.center_y)
                elem_data.append(elem.width)
                elem_data.append(elem.length)
                elem_data.append(elem.heading if elem.heading_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            elif isinstance(elem, ParkingSlot):
                types.append(TrafficElementType.PARKING_SLOT)
                elem_data.append(elem.center_x)
                elem_data.append(elem.center_y)
                elem_data.append(elem.width)
                elem_data.append(elem.length)
                elem_data.append(elem.heading if elem.heading_valid else None)
                elem_data.append(elem.occupancy.val)
                elem_data.append(None)  # 预留
            elif isinstance(elem, ZebraCrossing):
                types.append(TrafficElementType.ZEBRA_CROSSING)
                elem_data.append(elem.near_distance)
                elem_data.append(elem.far_distance if elem.far_distance_valid else None)
                elem_data.append(elem.heading if elem.heading_valid else None)
                elem_data.append(None)  # 预留
                elem_data.append(None)  # 预留
            if len(elem_data) > 0:
                offsets.append(total_data_size)
                sizes.append(len(elem_data))
                datas.append(elem_data)
                total_data_size += len(elem_data)
        output.significant = 1 + len(self.elements) * 6 + total_data_size
        output.values = []
        output.values.append(len(self.elements))
        for i in range(0, len(self.elements)):
            output.values.append(offsets[i])
            output.values.append(sizes[i])
            output.values.append(types[i].val)
            output.values.append(self.elements[i].id)
            output.values.append(self.elements[i].raw_id if self.elements[i].raw_id_valid else None)
            output.values.append(None)
        for elem_data in datas:
            output.values += elem_data
        return output


def _conv_traffic_sample_v1(gs):
    values_count = len(gs.values)
    if values_count < 1:
        return None
    elem_count = int(gs.values[0]) if gs.values[0] is not None else 0
    if values_count < 1 + elem_count * 3:
        return None
    output = TrafficSample()
    output.time = gs.time
    for i in range(0, elem_count):
        if gs.values[1 + 3 * i] is None or gs.values[2 + 3 * i] is None or gs.values[3 + 3 * i] is None:
            continue
        type = int(gs.values[1 + 3 * i])
        eo = int(gs.values[2 + 3 * i]) + 1 + elem_count * 3
        es = int(gs.values[3 + 3 * i])
        if values_count < eo + es:
            return None
        elem = None
        if type == TrafficElementType.SPEED_LIMIT.val:
            if gs.values[eo] is not None:
                elem = SpeedLimit()
                elem.limit_speed = int(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.pos_x_valid = True
                    elem.pos_x = float(gs.values[eo + 1])
                if gs.values[eo + 2] is not None:
                    elem.pos_y_valid = True
                    elem.pos_y = float(gs.values[eo + 2])
        elif type == TrafficElementType.STOP_SIGN.val:
            elem = StopSign()
            if gs.values[eo] is not None:
                elem.pos_x_valid = True
                elem.pos_x = float(gs.values[eo])
            if gs.values[eo + 1] is not None:
                elem.pos_y_valid = True
                elem.pos_y = float(gs.values[eo + 1])
        elif type == TrafficElementType.TRAFFIC_LIGHT.val:
            if gs.values[eo] is not None:
                elem = TrafficLight()
                elem.state = TrafficLightStateValue(int(gs.values[eo]))
                if gs.values[eo + 1] is not None:
                    elem.pos_x_valid = True
                    elem.pos_x = float(gs.values[eo + 1])
                if gs.values[eo + 2] is not None:
                    elem.pos_y_valid = True
                    elem.pos_y = float(gs.values[eo + 2])
                if gs.values[eo + 3] is not None and gs.values[eo + 4] is not None and gs.values[eo + 5] is not None and gs.values[eo + 6] is not None:
                    elem.arrows.valid = True
                    elem.arrows.go_straight = gs.values[eo + 3] == 1
                    elem.arrows.turn_left = gs.values[eo + 4] == 1
                    elem.arrows.turn_right = gs.values[eo + 5] == 1
                    elem.arrows.u_turn = gs.values[eo + 6] == 1
        elif type == TrafficElementType.STOP_LINE.val:
            if gs.values[eo] is not None:
                elem = StopLine()
                elem.distance = float(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 1])
        elif type == TrafficElementType.SPEED_BUMP.val:
            if gs.values[eo] is not None:
                elem = SpeedBump()
                elem.distance = float(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 1])
        elif type == TrafficElementType.ARROW_MARK.val:
            if gs.values[eo] is not None and gs.values[eo + 1] is not None and gs.values[eo + 2] is not None and gs.values[eo + 3] is not None:
                elem = ArrowMark()
                elem.arrows.valid = True
                elem.arrows.go_straight = gs.values[eo] == 1
                elem.arrows.turn_left = gs.values[eo + 1] == 1
                elem.arrows.turn_right = gs.values[eo + 2] == 1
                elem.arrows.u_turn = gs.values[eo + 3] == 1
                if gs.values[eo + 4] is not None:
                    elem.pos_x_valid = True
                    elem.pos_x = float(gs.values[eo + 4])
                if gs.values[eo + 5] is not None:
                    elem.pos_y_valid = True
                    elem.pos_y = float(gs.values[eo + 5])
        elif type == TrafficElementType.PROHIBITION_ZONE.val:
            if gs.values[eo] is not None and gs.values[eo + 1] is not None and gs.values[eo + 2] is not None and gs.values[eo + 3] is not None:
                elem = ProhibitionZone()
                elem.center_x = float(gs.values[eo])
                elem.center_y = float(gs.values[eo + 1])
                elem.width = float(gs.values[eo + 2])
                elem.length = float(gs.values[eo + 3])
                if gs.values[eo + 4] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 4])
        elif type == TrafficElementType.PARKING_SLOT.val:
            if gs.values[eo] is not None and gs.values[eo + 1] is not None and gs.values[eo + 2] is not None and gs.values[eo + 3] is not None:
                elem = ParkingSlot()
                elem.center_x = float(gs.values[eo])
                elem.center_y = float(gs.values[eo + 1])
                elem.width = float(gs.values[eo + 2])
                elem.length = float(gs.values[eo + 3])
                if gs.values[eo + 4] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 4])
        elif type == TrafficElementType.ZEBRA_CROSSING.val:
            if gs.values[eo] is not None:
                elem = ZebraCrossing()
                elem.near_distance = float(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.far_distance_valid = True
                    elem.far_distance = float(gs.values[eo + 1])
                if gs.values[eo + 2] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 2])
        if elem is not None:
            output.elements.append(elem)
    return output


def _conv_traffic_sample_v2(gs):
    values_count = len(gs.values)
    if values_count < 1:
        return None
    elem_count = int(gs.values[0]) if gs.values[0] is not None else 0
    if values_count < 1 + elem_count * 6:
        return None
    output = TrafficSample()
    output.time = gs.time
    for i in range(0, elem_count):
        if gs.values[1 + 6 * i] is None or gs.values[2 + 6 * i] is None or gs.values[3 + 6 * i] is None or gs.values[4 + 6 * i] is None:
            continue
        eo = int(gs.values[1 + 6 * i]) + 1 + elem_count * 6
        es = int(gs.values[2 + 6 * i])
        type = int(gs.values[3 + 6 * i])
        if values_count < eo + es:
            return None
        elem = None
        if type == TrafficElementType.SPEED_LIMIT.val:
            if gs.values[eo] is not None:
                elem = SpeedLimit()
                elem.limit_speed = int(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.pos_x_valid = True
                    elem.pos_x = float(gs.values[eo + 1])
                if gs.values[eo + 2] is not None:
                    elem.pos_y_valid = True
                    elem.pos_y = float(gs.values[eo + 2])
                if gs.values[eo + 3] is not None:
                    elem.pos_z_valid = True
                    elem.pos_z = float(gs.values[eo + 3])
        elif type == TrafficElementType.STOP_SIGN.val:
            elem = StopSign()
            if gs.values[eo] is not None:
                elem.pos_x_valid = True
                elem.pos_x = float(gs.values[eo])
            if gs.values[eo + 1] is not None:
                elem.pos_y_valid = True
                elem.pos_y = float(gs.values[eo + 1])
            if gs.values[eo + 2] is not None:
                elem.pos_z_valid = True
                elem.pos_z = float(gs.values[eo + 2])
        elif type == TrafficElementType.TRAFFIC_LIGHT.val:
            if gs.values[eo] is not None:
                elem = TrafficLight()
                elem.state = TrafficLightStateValue(int(gs.values[eo]))
                if gs.values[eo + 1] is not None:
                    elem.pos_x_valid = True
                    elem.pos_x = float(gs.values[eo + 1])
                if gs.values[eo + 2] is not None:
                    elem.pos_y_valid = True
                    elem.pos_y = float(gs.values[eo + 2])
                if gs.values[eo + 3] is not None:
                    elem.pos_z_valid = True
                    elem.pos_z = float(gs.values[eo + 3])
                if gs.values[eo + 4] is not None and gs.values[eo + 5] is not None and gs.values[eo + 6] is not None and gs.values[eo + 7] is not None:
                    elem.arrows.valid = True
                    elem.arrows.go_straight = gs.values[eo + 4] == 1
                    elem.arrows.turn_left = gs.values[eo + 5] == 1
                    elem.arrows.turn_right = gs.values[eo + 6] == 1
                    elem.arrows.u_turn = gs.values[eo + 7] == 1
        elif type == TrafficElementType.STOP_LINE.val:
            if gs.values[eo] is not None:
                elem = StopLine()
                elem.distance = float(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 1])
        elif type == TrafficElementType.SPEED_BUMP.val:
            if gs.values[eo] is not None:
                elem = SpeedBump()
                elem.distance = float(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 1])
        elif type == TrafficElementType.ARROW_MARK.val:
            if gs.values[eo] is not None and gs.values[eo + 1] is not None and gs.values[eo + 2] is not None and gs.values[eo + 3] is not None:
                elem = ArrowMark()
                elem.arrows.valid = True
                elem.arrows.go_straight = gs.values[eo] == 1
                elem.arrows.turn_left = gs.values[eo + 1] == 1
                elem.arrows.turn_right = gs.values[eo + 2] == 1
                elem.arrows.u_turn = gs.values[eo + 3] == 1
                if gs.values[eo + 4] is not None:
                    elem.pos_x_valid = True
                    elem.pos_x = float(gs.values[eo + 4])
                if gs.values[eo + 5] is not None:
                    elem.pos_y_valid = True
                    elem.pos_y = float(gs.values[eo + 5])
        elif type == TrafficElementType.PROHIBITION_ZONE.val:
            if gs.values[eo] is not None and gs.values[eo + 1] is not None and gs.values[eo + 2] is not None and gs.values[eo + 3] is not None:
                elem = ProhibitionZone()
                elem.center_x = float(gs.values[eo])
                elem.center_y = float(gs.values[eo + 1])
                elem.width = float(gs.values[eo + 2])
                elem.length = float(gs.values[eo + 3])
                if gs.values[eo + 4] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 4])
        elif type == TrafficElementType.PARKING_SLOT.val:
            if gs.values[eo] is not None and gs.values[eo + 1] is not None and gs.values[eo + 2] is not None and gs.values[eo + 3] is not None:
                elem = ParkingSlot()
                elem.center_x = float(gs.values[eo])
                elem.center_y = float(gs.values[eo + 1])
                elem.width = float(gs.values[eo + 2])
                elem.length = float(gs.values[eo + 3])
                if gs.values[eo + 4] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 4])
                if gs.values[eo + 5] is not None:
                    elem.occupancy = ParkingSlotOccupancy(int(gs.values[eo + 5]))
        elif type == TrafficElementType.ZEBRA_CROSSING.val:
            if gs.values[eo] is not None:
                elem = ZebraCrossing()
                elem.near_distance = float(gs.values[eo])
                if gs.values[eo + 1] is not None:
                    elem.far_distance_valid = True
                    elem.far_distance = float(gs.values[eo + 1])
                if gs.values[eo + 2] is not None:
                    elem.heading_valid = True
                    elem.heading = float(gs.values[eo + 2])
        if elem is not None:
            elem.id = int(gs.values[4 + 6 * i])
            if gs.values[5 + 6 * i] is not None:
                elem.raw_id_valid = True
                elem.raw_id = int(gs.values[5 + 6 * i])
            output.elements.append(elem)
    return output


# 获取TrafficSample，用于样本输入
def get_traffic_sample(channel):
    s1 = None
    s2 = None
    w1 = 0.0
    w2 = 0.0
    protocol_id_v1 = 'traffic-sample-v1@' + str(channel)
    protocol_id_v2 = 'traffic-sample-v2@' + str(channel)
    if protocol_id_v2 in bi.input_samples:
        pair = bi.input_samples[protocol_id_v2]
        s1 = _conv_traffic_sample_v2(pair.sample1)
        w1 = pair.weight1
        s2 = _conv_traffic_sample_v2(pair.sample2)
        w2 = pair.weight2
    elif protocol_id_v1 in bi.input_samples:
        pair = bi.input_samples[protocol_id_v1]
        s1 = _conv_traffic_sample_v1(pair.sample1)
        w1 = pair.weight1
        s2 = _conv_traffic_sample_v1(pair.sample2)
        w2 = pair.weight2
    if s1 is not None and s2 is not None:
        return s1 if w1 > w2 else s2
    return None
